from django.http import HttpResponse
from django.shortcuts import render
from django.views import View
from django.http import JsonResponse

# Create your views here.


"""
图形验证码的实现
前端
    拼接一个 url，然后给 img ，img就会发起请求(或者点击验证码图片他就会刷新,刷新就会发起请求)
    url=http://ip:port/image_code/uuid/
后端
    请求 接收路由中的 uuid
    业务逻辑 生成图片验证码和图片二进制，通过redis把图片验证码保存起来
    响应 返回图片二进制
    路由:     GET image_codes/uuid/
    步骤:
        1.接收路由中的 uuid
        2.生成图片验证码和图片二进制
        3.通过redis把图片验证码保存起来
        4.返回图片二进制
        5.比对redis中存储的验证码和用户输入的验证码
"""


# 图片验证码类
class ImageCodeView(View):
    # 获取uuid
    # 1.接收路由中的 uuid
    def get(self, request, uuid):

        # 2.生成图片验证码和图片二进制
        from libs.captcha.captcha import captcha
        # text 是图片验证码的内容    image 是图片的二进制
        text, image = captcha.generate_captcha()

        # 3.通过redis把图片验证码保存起来
        from django_redis import get_redis_connection
        redis_cli = get_redis_connection('code')
        # setex: name(key),time,value
        redis_cli.setex(uuid, 100, text)

        # 4.返回图片二进制
        # 因为图片为image，所以不能返回json数据、
        # 下面的content_type表示返回数据类型
        # 语法形式为:大类/小类
        return HttpResponse(image, content_type='image/jpeg')


"""
短信验证码的实现
前端
    当用户输入完手机号，图片验证码后，前端发送一个axios请求
    url中会携带三个参数，手机号,用户输入的图形验证码,验证码对应的图片id
后端
    请求: 接收请求，获取参数(路由有手机号，用户的图片验证码和uuid在查询字符串中)
    业务逻辑: 验证参数，验证图片验证码，生成短信验证码，保存短信验证码，发送短信验证码
    响应 返回响应 {'code': 0, 'errmsg': 'ok'}
    路由: GET  sms_codes/mobile/?image_code/?uuid/
    
    步骤:
        1.获取请求参数
        2.验证参数
        3.验证图片验证码
        4.生成短信验证码
        5.保存短信验证码
        6.发送短信验证码
        7.返回响应
"""


class SmsCodeView(View):
    def get(self, request, mobile):

        # 1.获取请求参数
        # 用户输入
        image_code = request.GET.get('image_code')
        # 对应的验证码图片id
        uuid = request.GET.get('image_code_id')

        # 2.验证参数
        if not all([image_code, uuid]):
            return JsonResponse({'code': 400, 'errmsg': '参数不全'})

        # 3.验证图片验证码
        from django_redis import get_redis_connection
        redis_cli = get_redis_connection('code')
        # 判断图片验证码是否过期
        redis_image_code = redis_cli.get(uuid)
        if redis_image_code is None:
            return JsonResponse({'code': 400, 'errmsg': '图片验证码已过期，请点击刷新'})
        # 对比用户输入和数据库存储是否一致
        if image_code.lower() != redis_image_code.decode().lower():
            return JsonResponse({'code': 400, 'errmsg': '验证码错误，请重新输入'})

        # 提取发送短信的标记判断是否重复请求
        send_flag = redis_cli.get('send_flag%s' % mobile)
        if send_flag is not None:
            return JsonResponse({'code': 400, 'errmsg': '请勿重复请求短信验证码！'})

        # 4.生成短信验证码
        from random import randint
        sms_code = '%06d' % randint(0, 999999)

        # 管道3步
        redis_cli = get_redis_connection('verify_code')
        # 1. 建立一个管道
        pipeline = redis_cli.pipeline()
        # 2. 管道效果指令    保存短信验证码,并且保存标记
        pipeline.setex(mobile, 300, sms_code)
        pipeline.setex('send_flag_%s' % mobile, 60, 1)
        # 3. 管道执行指令
        pipeline.execute()

        """
        下面是使用redis直接操作，相当于每次我执行都会进行一次连接,
        而上面使用管道相当于是连接成功后将要执行的命令集合到一起,依次执行,能极大提高效率
        管道的实现原理是队列,先进先出
        """
        # # 5.保存短信验证码,并且保存标记
        # redis_cli.setex(mobile, 300, sms_code)
        # redis_cli.setex('send_flag_%s' % mobile, 60, 1)

        # 6.发送短信验证码
        # from libs.yuntongxun.sms import CCP
        # CCP().send_template_sms(mobile, [sms_code, 5], 1)
        from celery_tasks.sms.tasks import celery_send_sms_code
        # delay的参数等同于任务函数的参数
        celery_send_sms_code.delay(mobile, sms_code)

        # 7.返回响应
        return JsonResponse({'code': 0, 'errmsg': 'ok'})
